package com.yuanlang.common.util;
import java.awt.geom.Point2D;
/**
 * @author lany
 * 2017-10-20
 */

/**
 * 地理坐标换算工具
 */
public class CoordDisposeUtil
{
    /// <summary>
    /// 经纬度坐标
    /// </summary>
    public static class Degree
    {
        Degree(double lat, double lng)
        {
            this.lat = new java.text.DecimalFormat("#.000000").format(lat);
            this.lng = new java.text.DecimalFormat("#.000000").format(lng);
        }
        private String lat;
        private String lng;

        public double getLat() {
            return Double.parseDouble(lat);
        }

        public void setLat(double lat) {
            this.lat = new java.text.DecimalFormat("#.000000").format(lat);
        }

        public double getLng() {
            return Double.parseDouble(lng);
        }

        public void setLng(double lng) {
            this.lng = new java.text.DecimalFormat("#.000000").format(lng);
        }
    }

    private static final double EARTH_RADIUS = 6371004;//地球半径(米)

    /// <summary>
    /// 角度数转换为弧度公式
    /// </summary>
    /// <param name="d"></param>
    /// <returns></returns>
    private static double radians(double d)
    {
        return d * Math.PI / 180.0;
    }

    /// <summary>
    /// 弧度转换为角度数公式
    /// </summary>
    /// <param name="d"></param>
    /// <returns></returns>
    private static double degrees(double d)
    {
        return d * (180 / Math.PI);
    }

    /// <summary>
    /// 计算两个经纬度之间的直接距离
    /// </summary>

    public static double GetDistance(Degree Degree1, Degree Degree2)
    {
        double radLat1 = radians(Degree1.getLat());
        double radLat2 = radians(Degree2.getLat());
        double a = radLat1 - radLat2;
        double b = radians(Degree1.getLng()) - radians(Degree2.getLng());

        double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) +
                Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
        s = s * CoordDisposeUtil.EARTH_RADIUS;
        s = Math.round(s * 10000) / 10000;
        return s;
    }

    /// <summary>
    /// 计算两个经纬度之间的直接距离(google 算法)
    /// </summary>
    public static double GetDistanceGoogle(Degree Degree1, Degree Degree2)
    {
        double radLat1 = radians(Degree1.getLat());
        double radLng1 = radians(Degree1.getLng());
        double radLat2 = radians(Degree2.getLat());
        double radLng2 = radians(Degree2.getLng());

        double s = Math.acos(Math.cos(radLat1) * Math.cos(radLat2) * Math.cos(radLng1 - radLng2) + Math.sin(radLat1) * Math.sin(radLat2));
        s = s * EARTH_RADIUS;
        s = Math.round(s * 10000) / 10000;
        return s;
    }

    /// <summary>
    /// 以一个经纬度为中心计算出四个顶点
    /// </summary>
    /// <param name="distance">半径(米)</param>
    /// <returns></returns>
    public static Degree[] GetDegreeCoordinates(Degree Degree1, double distance)
    {
        Point2D.Double pDiff = GetDegreeDiff(Degree1.getLat(),distance);
        double dlng = pDiff.getY();
        double dlat = pDiff.getX();

        return new Degree[] { new Degree(Degree1.getLat() + dlat, Degree1.getLng() - dlng),//left-top
                new Degree(Degree1.getLat() - dlat, Degree1.getLng() - dlng),//left-bottom
                new Degree(Degree1.getLat() + dlat, Degree1.getLng() + dlng),//right-top
                new Degree(Degree1.getLat() - dlat, Degree1.getLng() + dlng) //right-bottom
        };

    }

    /// <summary>
    /// 以一个经纬度为中心计算出经纬度差值
    /// </summary>
    /// <param name="distance">半径(米)</param>
    /// <returns></returns>
    public static Point2D.Double GetDegreeDiff(double lat, double distance)
    {
        double dlng = 2 * Math.asin(Math.sin(distance / (2 * EARTH_RADIUS)) / Math.cos(Math.toRadians(lat)));
        dlng = degrees(dlng);//一定转换成角度数

        double dlat = distance / EARTH_RADIUS;
        dlat = degrees(dlat);//一定转换成角度数

        return new Point2D.Double(dlng,dlat);
        };

}
